package com.kxmall.web.controller.rider.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kxmall.common.core.domain.PageQuery;
import com.kxmall.common.core.page.TableDataInfo;
import com.kxmall.common.enums.RiderStatusType;
import com.kxmall.common.enums.RiderWeekStatusType;
import com.kxmall.common.enums.RiderWorkStateType;
import com.kxmall.common.enums.RoleStatusType;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.utils.StringUtils;
import com.kxmall.common.utils.file.FileUtils;
import com.kxmall.huishou.domain.HsRecyclerApply;
import com.kxmall.huishou.mapper.HsRecyclerApplyMapper;
import com.kxmall.rider.domain.KxRider;
import com.kxmall.rider.domain.KxRiderCycle;
import com.kxmall.rider.domain.bo.KxRiderBo;
import com.kxmall.rider.domain.vo.KxRiderVo;
import com.kxmall.rider.mapper.KxRiderCycleMapper;
import com.kxmall.rider.mapper.KxRiderMapper;
import com.kxmall.storage.domain.KxStorage;
import com.kxmall.storage.mapper.KxStorageMapper;
import com.kxmall.web.controller.rider.service.IKxRiderService;
import com.kxmall.wechat.WxMpConfiguration;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 配送Service业务层处理
 *
 * @author kxmall
 * @date 2023-09-21
 */
@RequiredArgsConstructor
@Service
public class KxRiderServiceImpl implements IKxRiderService {

    private final KxRiderMapper baseMapper;

    private final KxRiderCycleMapper riderCycleMapper;

    private final KxStorageMapper storageMapper;
    private final HsRecyclerApplyMapper hsRecyclerApplyMapper;

    // 初始密码
    private static final String ININT_PASSWORD = "123456";

    /**
     * 查询配送
     */
    @Override
    public KxRiderVo queryById(Long id) {
        KxRiderVo riderVo = baseMapper.selectVoById(id);
        if (riderVo != null) {

            QueryWrapper<KxRiderCycle> wrapper = new QueryWrapper<>();
            wrapper.eq("rider_id", id);
            List<KxRiderCycle> riderCycles = riderCycleMapper.selectList(wrapper);
            if (riderCycles != null && riderCycles.size() > 0) {
                riderVo.setWeekNumberIds(riderCycles.stream().map(KxRiderCycle::getWeekNumber).collect(Collectors.toList()));
            }
            return riderVo;
        }
        throw new ServiceException("配送员不存在");
    }

    /**
     * 查询配送列表
     */
    @Override
    public TableDataInfo<KxRiderVo> queryPageList(KxRiderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<KxRider> lqw = buildQueryWrapper(bo);
        Page<KxRiderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询配送列表
     */
    @Override
    public List<KxRiderVo> queryList(KxRiderBo bo) {
        LambdaQueryWrapper<KxRider> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<KxRider> buildQueryWrapper(KxRiderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<KxRider> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getName()), KxRider::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getDeliveryStart()), KxRider::getDeliveryStart, bo.getDeliveryStart());
        lqw.eq(StringUtils.isNotBlank(bo.getDeliveryEnd()), KxRider::getDeliveryEnd, bo.getDeliveryEnd());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), KxRider::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getAvatarUrl()), KxRider::getAvatarUrl, bo.getAvatarUrl());
        lqw.eq(StringUtils.isNotBlank(bo.getLastLoginIp()), KxRider::getLastLoginIp, bo.getLastLoginIp());
        lqw.eq(bo.getGmtLastLogin() != null, KxRider::getGmtLastLogin, bo.getGmtLastLogin());
        lqw.eq(bo.getLoginType() != null, KxRider::getLoginType, bo.getLoginType());
        lqw.eq(StringUtils.isNotBlank(bo.getOpenId()), KxRider::getOpenId, bo.getOpenId());
        lqw.eq(bo.getState() != null, KxRider::getState, bo.getState());
        lqw.eq(bo.getWorkState() != null, KxRider::getWorkState, bo.getWorkState());
        lqw.eq(StringUtils.isNotBlank(bo.getPassword()), KxRider::getPassword, bo.getPassword());
        lqw.eq(bo.getStorageId() != null, KxRider::getStorageId, bo.getStorageId());
        lqw.eq(bo.getDeliveryRadius() != null, KxRider::getDeliveryRadius, bo.getDeliveryRadius());
        lqw.in(!CollectionUtils.isEmpty(bo.getStorageIds()), KxRider::getStorageId, bo.getStorageIds());
        return lqw;
    }

    /**
     * 新增配送
     */
    @Override
    public Boolean insertByBo(KxRiderBo bo) {
        if (StringUtils.isEmpty(bo.getPhone())) {
            throw new ServiceException("配送员手机号不能为空");
        }
        QueryWrapper<KxRider> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", bo.getPhone());
        Long phoneCount = baseMapper.selectCount(wrapper);
        if (phoneCount > 0) {
            throw new ServiceException("配送员手机号已经存在");
        }
        KxRider add = BeanUtil.toBean(bo, KxRider.class);

        if (StringUtils.isEmpty(bo.getNewPassword())) {
            add.setPassword(ININT_PASSWORD);
        } else {
            add.setPassword(bo.getNewPassword());
        }
        String cryptPassword = Md5Crypt.md5Crypt(add.getPassword().getBytes(), "$1$" + bo.getPhone().substring(0, 7));
        add.setPassword(cryptPassword);
        add.setState(RiderStatusType.NOMRAL.getCode());
        add.setWorkState(RiderWeekStatusType.REST.getCode());
        add.setCreateBy(bo.getUserName());
        add.setUpdateBy(bo.getUserName());
        Date now = new Date();
        add.setCreateTime(now);
        add.setUpdateTime(now);
        add.setLoginType(0);
        if (baseMapper.insert(add) > 0) {
            List<Long> weekNumberIds = bo.getWeekNumberIds();
            if (weekNumberIds != null && weekNumberIds.size() > 0) {
                Long riderDOId = add.getId();
                KxRiderCycle riderCycle;
                List<KxRiderCycle> riderCycleDOList = new ArrayList<>();
                for (Long weekNumber : weekNumberIds) {
                    riderCycle = new KxRiderCycle();
                    riderCycle.setRiderId(riderDOId);
                    riderCycle.setWeekNumber(weekNumber);
                    riderCycleDOList.add(riderCycle);
                }
                riderCycleMapper.insertBatch(riderCycleDOList);
            }
            add.setPassword(null);
            return true;
        }
        throw new ServiceException("管理员系统未知异常");
    }

    /**
     * 修改配送
     */
    @Override
    public Boolean updateByBo(KxRiderBo bo) {
        if (StringUtils.isEmpty(bo.getPhone())) {
            throw new ServiceException("配送员手机号不能为空");
        }
        KxRider oldKxRider = baseMapper.selectById(bo.getId());
        if (oldKxRider == null) {
            throw new ServiceException("配送员不存在");
        }

        QueryWrapper<KxRider> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", bo.getPhone());
        wrapper.ne("id", oldKxRider.getId());
        long count = baseMapper.selectCount(wrapper);
        if (count > 0) {
            throw new ServiceException("配送员手机号已经存在");
        }

        KxRider update = BeanUtil.toBean(bo, KxRider.class);
        if (StringUtils.isNotEmpty(bo.getNewPassword())) {
            String cryptPassword = Md5Crypt.md5Crypt(bo.getNewPassword().getBytes(), "$1$" + bo.getPhone().substring(0, 7));
            update.setPassword(cryptPassword);
        }
        update.setUpdateBy(bo.getUserName());
        Date now = new Date();
        update.setUpdateTime(now);
        Integer oldState = oldKxRider.getState();
        // 如果是启用被禁用的回收员账号
        if (update.getState() == RoleStatusType.ACTIVE.getCode() && oldState == RoleStatusType.LOCK.getCode()) {
            LambdaQueryWrapper<HsRecyclerApply> applyLambdaQueryWrapper = new LambdaQueryWrapper<>();
            applyLambdaQueryWrapper.eq(HsRecyclerApply::getUserId, bo.getId());
            List<HsRecyclerApply> hsRecyclerApplies = hsRecyclerApplyMapper.selectList(applyLambdaQueryWrapper);
            // 如果已存在申请，那么需要判断是否通过
            if (CollUtil.isNotEmpty(hsRecyclerApplies)) {
                long count1 = hsRecyclerApplies.stream().filter(item -> item.getStatus() == 1L).count();
                if (count1 == 0) {
                    throw new ServiceException("请先同意该派送员的申请");
                }
            }
        }

        if (baseMapper.updateById(update) > 0) {
            Long riderDOId = bo.getId();
            QueryWrapper<KxRiderCycle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("rider_id", riderDOId);
            riderCycleMapper.delete(queryWrapper);
            List<Long> weekNumberIds = bo.getWeekNumberIds();
            if (weekNumberIds != null && weekNumberIds.size() > 0) {
                KxRiderCycle riderCycleDO;
                List<KxRiderCycle> riderCycleDOList = new ArrayList<>();
                for (Long weekNumber : weekNumberIds) {
                    riderCycleDO = new KxRiderCycle();
                    riderCycleDO.setRiderId(riderDOId);
                    riderCycleDO.setWeekNumber(weekNumber);
                    riderCycleDOList.add(riderCycleDO);
                }
                riderCycleMapper.insertBatch(riderCycleDOList);
            }
            return true;
        }
        throw new ServiceException("管理员系统未知异常");
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(KxRider entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除配送
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public List<KxRiderVo> getRiderByStorageId(Long storageId) {

        QueryWrapper<KxRider> wrapper = new QueryWrapper<>();
        if (storageId != null) {
            wrapper.eq("storage_id", storageId);
        }
        KxStorage kxStorage = storageMapper.selectById(storageId);
        wrapper.eq("state", RiderStatusType.NOMRAL.getCode());
        wrapper.eq("work_state", RiderWeekStatusType.BUSINESS.getCode());
        int state = RiderStatusType.NOMRAL.getCode();
        int workState = RiderWeekStatusType.BUSINESS.getCode();
        //过滤不在工作区间
        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat("HH:mm");
        String nowDate = format.format(now);
        List<KxRider> riderDOList = baseMapper.selectListByWorkTime(storageId, state, workState, getWeekOfDate(new Date()));
        if (CollectionUtils.isEmpty(riderDOList)) {
            throw new ServiceException("不存在工作中的骑手");
        }
        List<KxRider> collect = riderDOList.stream().filter(x -> {
            try {
                return isEffectiveDate(nowDate, x.getDeliveryStart(), x.getDeliveryEnd());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return false;
        }).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)) {
            throw new ServiceException("不存在工作中的骑手", 500);
        }
        List<KxRiderVo> riderDOS = new ArrayList<>();
        for (KxRider riderDO : collect) {
            KxRiderVo riderDTO = new KxRiderVo();
            BeanUtils.copyProperties(riderDO, riderDTO);
            riderDTO.setAutomatic(kxStorage.getAutomatic());
            riderDOS.add(riderDTO);
        }
        //需要自动分配骑手
        if (kxStorage.getAutomatic() == 1) {
            Optional<KxRiderVo> any = riderDOS.stream().findAny();
            riderDOS = Collections.singletonList(any.get());
        }
        return riderDOS;
    }


    /**
     * 获取当前日期是星期几<br>
     *
     * @param dt
     * @return 当前日期是星期几
     */
    public static int getWeekOfDate(Date dt) {
        int[] weekDays = {7, 1, 2, 3, 4, 5, 6};
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
     *
     * @param nowDate   当前时间
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return
     * @author szh
     */
    public final boolean isEffectiveDate(String nowDate, String startDate, String endDate) throws ParseException {
        String format = "HH:mm";
        if (org.springframework.util.StringUtils.isEmpty(startDate)) {
            return false;
        }
        if (org.springframework.util.StringUtils.isEmpty(endDate)) {
            return false;
        }
        Date startTime = new SimpleDateFormat(format).parse(startDate);
        Date endTime = new SimpleDateFormat(format).parse(endDate);
        Date nowTime = new SimpleDateFormat(format).parse(nowDate);

        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }
        long now = nowTime.getTime();
        long begin = startTime.getTime();
        long end = endTime.getTime();
        return now > begin && now < end;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateStateToNomral(String idsJson) throws ServiceException {
        List<Long> ids = JSONObject.parseArray(idsJson, Long.class);
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("配送员不存在");
        }
        LambdaQueryWrapper<HsRecyclerApply> applyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        applyLambdaQueryWrapper.in(HsRecyclerApply::getUserId, ids);
        List<HsRecyclerApply> hsRecyclerApplies = hsRecyclerApplyMapper.selectList(applyLambdaQueryWrapper);
        // 如果已存在申请，那么需要判断是否通过
        if (CollUtil.isNotEmpty(hsRecyclerApplies)) {
            long count1 = hsRecyclerApplies.stream().filter(item -> item.getStatus() == 1L).count();
            if (count1 <ids.size()) {
                throw new ServiceException("请先同意派送员的申请");
            }
        }

        if (baseMapper.batchUpdateState(ids, RiderStatusType.NOMRAL.getCode()) <= 0) {
            throw new ServiceException("配送员不存在");
        }

        return "ok";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateStateToAbort(String idsJson) throws ServiceException {
        List<Long> ids = JSONObject.parseArray(idsJson, Long.class);
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("配送员不存在");
        }

        //禁用的同时，将状态调整为休息中
        if (baseMapper.batchUpdateState(ids, RiderStatusType.ABORT.getCode()) <= 0 || baseMapper.batchUpdateWeekState(ids, RiderWorkStateType.REST.getCode()) <= 0) {
            throw new ServiceException("配送员不存在");
        }
        return "ok";
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateBusinessWorkState(String idsJson) throws ServiceException {
        List<Long> ids = JSONObject.parseArray(idsJson, Long.class);
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("配送员不存在");
        }
        if (baseMapper.batchUpdateWeekState(ids, RiderWeekStatusType.BUSINESS.getCode()) <= 0) {
            throw new ServiceException("配送员不存在");
        }
        return "ok";
    }

    @Override
    public String updateBusinessStateToRest(String idsJson) throws ServiceException {
        List<Long> ids = JSONObject.parseArray(idsJson, Long.class);
        if (CollectionUtils.isEmpty(ids)) {
            throw new ServiceException("配送员不存在");
        }
        if (baseMapper.batchUpdateWeekState(ids, RiderWeekStatusType.REST.getCode()) <= 0) {
            throw new ServiceException("配送员不存在");
        }
        return "ok";
    }

    @Override
    public String getRiderQrcodeImage(Long riderId){
        try {
            if (ObjectUtils.isEmpty(riderId)) {
                throw new ServiceException("管理员系统未知异常");
            }
            Map<String, Object> sendObject = new HashMap<>(1);
            sendObject.put("riderId", riderId);
            WxMpQrCodeTicket mpQrCodeTicket = WxMpConfiguration.getWxMpService().getQrcodeService().qrCodeCreateTmpTicket(JSONObject.toJSONString(sendObject), 7200);
            File file = WxMpConfiguration.getWxMpService().getQrcodeService().qrCodePicture(mpQrCodeTicket);
            return FileUtils.fileToBase64(file);
        } catch (Exception e) {
            e.printStackTrace();
            return  null;
//            throw new ServiceException("管理员系统未知异常");
        }
    }
}
